package com.infosys.setl.fp.demo4;

import org.apache.commons.functor.UnaryFunction;
import org.apache.commons.functor.core.Constant;
import org.apache.commons.functor.core.IsEqual;
import org.apache.commons.functor.core.comparator.IsGreaterThanOrEqual;
import org.apache.commons.functor.core.composite.UnaryAnd;
import org.apache.commons.functor.core.composite.UnaryCompositeBinaryPredicate;
import org.apache.commons.functor.core.composite.UnaryOr;

import com.infosys.setl.fp.demo1.SetlItem;

public class TestD {
    public static void main(String[] args) {

        UnaryFunction<SetlItem, String> getItemCategory = new UnaryFunction<SetlItem, String>() {
            public String evaluate(SetlItem obj) {
                return obj.getCategory();
            }
        };

        UnaryFunction<SetlItem, Double> getItemPrice = new UnaryFunction<SetlItem, Double>() {
            public Double evaluate(SetlItem obj) {
                return new Double(obj.getPrice());
            }
        };
        //constant
        Constant<String> categoryA = new Constant<String>("A");
        Constant<String> categoryB = new Constant<String>("B");
        Constant<Double> usd100 = new Constant<Double>(new Double(100));
        Constant<Double> usd200 = new Constant<Double>(new Double(200));
        //is belongs to categoryA
        BinaryPredicateUnaryPredicate belongsToCategoryA
        //将后两个函数的输出，作为第一个函数的输入
        //UnaryCompositeBinaryPredicate = getItemCategory(x) isEqual categoryA(x)
        = new BinaryPredicateUnaryPredicate(new UnaryCompositeBinaryPredicate<SetlItem, SetlItem>(new IsEqual<String, String>(), getItemCategory, categoryA));
        //is belongs to categoryB
        BinaryPredicateUnaryPredicate belongsToCategoryB
        //UnaryCompositeBinaryPredicate = getItemCategory(x) isEqual categoryB(x)
        = new BinaryPredicateUnaryPredicate(new UnaryCompositeBinaryPredicate<SetlItem, SetlItem>(new IsEqual<String, String>(), getItemCategory, categoryB));
        //is greater than or equal 100
        BinaryPredicateUnaryPredicate moreThanUSD100
        //UnaryCompositeBinaryPredicate = getItemPrice(x) isGreaterThanOrEqual usd100(x)
        = new BinaryPredicateUnaryPredicate(new UnaryCompositeBinaryPredicate<SetlItem, SetlItem>(new IsGreaterThanOrEqual<Double>(), getItemPrice, usd100));
        //is greater than or equal 200
        BinaryPredicateUnaryPredicate moreThanUSD200
        //UnaryCompositeBinaryPredicate = getItemPrice(x) isGreaterThanOrEqual usd200(x)
        = new BinaryPredicateUnaryPredicate(new UnaryCompositeBinaryPredicate<SetlItem, SetlItem>(new IsGreaterThanOrEqual<Double>(), getItemPrice, usd200));

        UnaryOr<SetlItem> isEligibleForDiscount = new UnaryOr<SetlItem>()
        //belongsToCategoryA and moreThanUsd100
                .or(new UnaryAnd<SetlItem>().and(belongsToCategoryA).and(moreThanUSD100))
                //belongsToCategoryB and moreThanUsd200
                .or(new UnaryAnd<SetlItem>().and(belongsToCategoryB).and(moreThanUSD200));
        //test
        SetlItem item1 = new SetlItem("item1");
        item1.setPrice(350);
        item1.setCategory("A");
        SetlItem item2 = new SetlItem("item2");
        item2.setPrice(50);
        item2.setCategory("A");
        SetlItem item3 = new SetlItem("item3");
        item3.setPrice(200);
        item3.setCategory("B");
        testItem(item1, isEligibleForDiscount);
        testItem(item2, isEligibleForDiscount);
        testItem(item3, isEligibleForDiscount);
    }

    public static void testItem(SetlItem item, UnaryOr<SetlItem> isEligibleForDiscount) {
        if (isEligibleForDiscount.test(item)) {
            System.out.println("Item " + item.getName() + " is eligible for discount!");
        } else {
            System.out.println("Item " + item.getName() + " is not eligible for discount!");
        }
    }
}
